//
//  CLBuleToothTool.m
//  toroBracelet
//
//  Created by 丁益 on 16/8/15.
//  Copyright © 2016年 celi. All rights reserved.
//

#import "CLBuleToothTool.h"
#import "CLProfileInfo.h"



@interface CLBuleToothTool()<CBCentralManagerDelegate,CBPeripheralDelegate>{

    NSInteger  deviceConnectTimeOut;
}

@property (strong, nonatomic) CBCharacteristic *writeCharacteristic;   //写特性
@property (strong, nonatomic) NSMutableArray *peripherals;
@property (strong, nonatomic) NSTimer *connectTimer;
@end

@implementation CLBuleToothTool

static id _instace = nil;
+ (id)allocWithZone:(struct _NSZone *)zone{
    
    if (_instace == nil) {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            _instace = [super allocWithZone:zone];
        });
    }
    return _instace;
}

- (id)init{
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _instace = [super init];
        _centralManager=[[CBCentralManager alloc]initWithDelegate:self queue:nil];
    });
    return _instace;
}

+ (instancetype)sharedBuleToothTool{
    return [[self alloc] init];
}

//SingletonM(BuleToothTool)


- (CGFloat)minRssi{

    if (_minRssi == 0.0) {
        _minRssi = 40;
    }
    return _minRssi;
}

/**
 *  开始扫描
 */
- (void)StartScanBuleToothDevice{
    
    //添加扫描外围设备
    NSArray *uuidArray = [NSArray arrayWithObjects:[CBUUID UUIDWithString:kServiceUUID],[CBUUID UUIDWithString:kCharacteristicUUIDRead],[CBUUID UUIDWithString:kCharacteristicUUIDWrite],nil];
    
    //uuidArray传nil 表示扫描所有设备
    [self.centralManager scanForPeripheralsWithServices:nil options:nil];
    
}

- (void)scanBuleToothDeviceWithCentral:(CBCentralManager *)central{
    //添加扫描外围设备
    NSArray *uuidArray = [NSArray arrayWithObjects:[CBUUID UUIDWithString:kServiceUUID],[CBUUID UUIDWithString:kCharacteristicUUIDRead],[CBUUID UUIDWithString:kCharacteristicUUIDWrite],nil];
    
    //uuidArray传nil 表示扫描所有设备
    [central scanForPeripheralsWithServices:nil options:nil];
    
}

/**
 *  停止扫描
 */
- (void)stopScanBuleToothDevice{
    
    [self.centralManager stopScan];
}

#pragma mark - CBCentralManager代理方法

/**
 *  中心服务器状态更新后
 */
-(void)centralManagerDidUpdateState:(CBCentralManager *)central{
    switch (central.state) {
        case CBPeripheralManagerStatePoweredOn:{
            DLog(@"BLE已打开.");
            //扫描外围设备
            [self scanBuleToothDeviceWithCentral:central];
        }
            break;
        
        case CBPeripheralManagerStatePoweredOff:
            DLog(@"BLE已关闭.");
            break;
        default:
            DLog(@"未打开手机蓝牙功能");
            break;
    }
}
/**
 *  发现外围设备
 *
 *  @param central           中心设备
 *  @param peripheral        外围设备
 *  @param advertisementData 特征数据
 *  @param RSSI              信号质量（信号强度）
 */
-(void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI{
    
    DLog(@"发现外围设备...");
    DLog(@"peripheral.name = %@",peripheral.name);
    DLog(@"peripheral.identifier.UUIDString = %@",peripheral.identifier.UUIDString);
    
    // 设置过滤规则
    // 需要对连接到的外设进行过滤
    // 1.信号强度(40以上才连接)
    if (([peripheral.name rangeOfString:buleToothName].location !=NSNotFound)&&(ABS(RSSI.integerValue) > self.minRssi)) {
        if (peripheral) {
            //添加保存外围设备，注意如果这里不保存外围设备（或者说peripheral没有一个强引用，无法到达连接成功（或失败）的代理方法，因为在此方法调用完就会被销毁
            if(![self.peripherals containsObject:peripheral]){
                [self.peripherals addObject:peripheral];
            }
            
            if ([self.delegate respondsToSelector:@selector(scanBuleToothDeviceWithPeripheral:)]) {
                [self.delegate scanBuleToothDeviceWithPeripheral:self.peripherals];
            }
        }
    }
}

/**
 *  连接指定的设备
 *
 *  @param peripheral 外设
 */
-(BOOL)connect:(CBPeripheral *)peripheral{
    
    DLog(@"connect start");
    if (peripheral) {
    
        [self.centralManager connectPeripheral:peripheral
                                       options:[NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:CBConnectPeripheralOptionNotifyOnDisconnectionKey]];
    }
    
    
    _peripheral = nil;
    //开一个定时器监控连接超时的情况
    self.connectTimer = [NSTimer scheduledTimerWithTimeInterval:30.0f target:self selector:@selector(connectTimeout:) userInfo:peripheral repeats:NO];
    
    return (YES);
}


/**
 *  连接到外围设备
 */
-(void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral{
    
    DLog(@"连接外围设备成功!");
    //设置外围设备的代理为当前视图控制器
    peripheral.delegate=self;
    
    self.peripheral = peripheral;
    self.connectPeripheral = peripheral;
    [[CLProfileInfo sharedProfileInfo] setUuidStringAndCache:peripheral.identifier.UUIDString];

    //外围设备开始寻找服务
    //[peripheral discoverServices:@[[CBUUID UUIDWithString:kServiceUUID]]];
    
    [peripheral discoverServices:nil];
    
    if ([self.delegate respondsToSelector:@selector(buleToothTool:didConnectPeripheral:)]) {
        [self.delegate buleToothTool:self didConnectPeripheral:peripheral];
    }
}

/**
 *  连接外围设备失败
 */
-(void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error{
    
    DLog(@"连接外围设备失败!");
    if ([self.delegate respondsToSelector:@selector(buleToothTool:didFailToConnectPeripheral:error:)]) {
        [self.delegate buleToothTool:self didFailToConnectPeripheral:peripheral error:error];
    }
}

/**
 *  是否还建立连接
 */
-(BOOL)isConnected
{
    return self.peripheral != nil;
}

/**
 *  断开连接
 */
- (void)cancelPeripheralConnection{
    
    DLog(@"蓝牙外设已经断开了-------");
    if (self.peripheral) {
        [self.centralManager cancelPeripheralConnection:self.peripheral];
        self.peripheral = nil;
    }
    DLog("self.peripheral = %@",self.peripheral);
}


/**
 *  判断蓝牙设备是否已经断开了
 *  Yes->连接  No->断开
 */
- (bool)isDeviceConnect{

    //10s没有读取到RISS值就判断蓝牙设备断开了
    if (deviceConnectTimeOut > 5) {
        deviceConnectTimeOut = 0;
        [[CLDeviceInfo sharedDeviceInfo] setIsLoginDevice:NO];
        //重新连接
        if (self.connectPeripheral) {
            [self connect:self.connectPeripheral];
        }
        
        return NO;
    }
    deviceConnectTimeOut++;
    return YES;
}

#pragma mark -timer
- (void)stopTimer{
    [self.connectTimer invalidate];
    self.connectTimer = nil;
}

- (void)connectTimeout:(NSTimer*)timer{
    
    [self stopTimer];
    if ([self.delegate respondsToSelector:@selector(connectBuleToothDeviceTimeOut)]) {
        [self.delegate connectBuleToothDeviceTimeOut];
    }
    
}


#pragma mark - CBPeripheral 代理方法
- (void)peripheral:(CBPeripheral *)peripheral didReadRSSI:(NSNumber *)RSSI error:(NSError *)error {
//    DLog(@"didReadRSSI = %@",RSSI);
    deviceConnectTimeOut = 0;
}


/**
 *  外围设备寻找到服务后
 */
-(void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error{
    
    DLog(@"已发现可用服务...");
    if(error){
        DLog(@"外围设备寻找服务过程中发生错误，错误信息：%@",error.localizedDescription);
    }
    //遍历查找到的服务
    /*CBUUID *serviceUUID=[CBUUID UUIDWithString:kServiceUUID];
     CBUUID *characteristicUUID=[CBUUID UUIDWithString:kCharacteristicUUID];
     for (CBService *service in peripheral.services) {
     if([service.UUID isEqual:serviceUUID]){
     //外围设备查找指定服务中的特征
     [peripheral discoverCharacteristics:@[characteristicUUID] forService:service];
     }
     }*/
    
    for (CBService *service in peripheral.services){
        
        NSLog(@"service = %@",service);
        NSLog(@"Service found with UUID: %@", service.UUID);
        //外围设备查找指定服务中的特征
        [self.peripheral discoverCharacteristics:nil forService:service];
    }
}

/**
 *  外围设备寻找到特征后
 */
-(void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error{
    
    DLog(@"已发现可用特征...");
    if (error) {
        DLog(@"外围设备寻找特征过程中发生错误，错误信息：%@",error.localizedDescription);
    }
    //遍历服务中的特征
    //    CBUUID *serviceUUID=[CBUUID UUIDWithString:kServiceUUID];
    //    CBUUID *characteristicUUID=[CBUUID UUIDWithString:kCharacteristicUUID];
    //    if ([service.UUID isEqual:serviceUUID]) {
    //        for (CBCharacteristic *characteristic in service.characteristics) {
    //            if ([characteristic.UUID isEqual:characteristicUUID]) {
    //
    //                NSLog(@"Discovered write characteristics:%@ for service: %@", characteristic.UUID, service.UUID);
    //                _writeCharacteristic = characteristic;//保存写的特征
    //                //情景一：通知
    //                /*找到特征后设置外围设备为已通知状态（订阅特征）：
    //                 *1.调用此方法会触发代理方法：-(void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
    //                 *2.调用此方法会触发外围设备的订阅代理方法
    //                 */
    //                [peripheral setNotifyValue:YES forCharacteristic:characteristic];
    //                //情景二：读取
    //                [peripheral readValueForCharacteristic:characteristic];
    //                if(characteristic.value){
    //                    NSString *value=[[NSString alloc]initWithData:characteristic.value encoding:NSUTF8StringEncoding];
    //                    NSLog(@"读取到特征值：%@",value);
    //                }
    //            }
    //        }
    //    }
    
    
#warning 针对ID进行过滤
    for (CBCharacteristic *characteristic in service.characteristics) {
        
        NSLog(@"Discovered write characteristics:%@ for service: %@", characteristic.UUID, service.UUID);
        
        NSString *nusService = [NSString stringWithFormat:@"%@",characteristic.UUID];
//        if ([nusService isEqualToString:@"6E400003-B5A3-F393-E0A9-E50E24DCCA9A"]) {
            _writeCharacteristic = characteristic;//保存写的特征
//        }
        
        //情景一：通知
        /*找到特征后设置外围设备为已通知状态（订阅特征）：
         *1.调用此方法会触发代理方法：-(void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
         *2.调用此方法会触发外围设备的订阅代理方法
         */
        [peripheral setNotifyValue:YES forCharacteristic:characteristic];
        
        //情景二：读取
        /*[peripheral readValueForCharacteristic:characteristic];
        if(characteristic.value){
            NSString *value=[[NSString alloc]initWithData:characteristic.value encoding:NSUTF8StringEncoding];
            NSLog(@"读取到特征值：%@",value);
        }*/
    }
}

//特征值被更新后
-(void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
    
    DLog(@"收到特征更新通知...");
    if (error) {
        DLog(@"更新通知状态时发生错误，错误信息：%@",error.localizedDescription);
    }
    //给特征值设置新的值
    CBUUID *characteristicUUID=[CBUUID UUIDWithString:kCharacteristicUUIDWrite];
    if ([characteristic.UUID isEqual:characteristicUUID]) {
        if (characteristic.isNotifying) {
            if (characteristic.properties==CBCharacteristicPropertyNotify) {
                DLog(@"已订阅特征通知.");
                return;
            } else if (characteristic.properties ==CBCharacteristicPropertyRead) {
                //从外围设备读取新值,调用此方法会触发代理方法：-(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error
                [peripheral readValueForCharacteristic:characteristic];
            }
            
        } else {
            DLog(@"停止已停止.");
            //取消连接
            [self.centralManager cancelPeripheralConnection:peripheral];
        }
    }
}

/**
 *  更新特征值后（调用readValueForCharacteristic:方法或者外围设备在订阅后更新特征值都会调用此代理方法
 */
-(void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error{
    
    if (error) {
        DLog(@"更新特征值时发生错误，错误信息：%@",error.localizedDescription);
        return;
    }
    if (characteristic.value) {
        NSString *value= [NSString string];
//       value=[[NSString alloc]initWithData:characteristic.value encoding:NSUTF8StringEncoding];
        Byte *testByte = (Byte *)[characteristic.value bytes];
        for (int i=0; i<characteristic.value.length; i++) {
            //DLog(@"testByte --- %d",testByte[i]);
            value = [NSString stringWithFormat:@"%@ %d",value,testByte[i]];
        }
        //DLog(@"value = %@",value);
        if([self.delegate respondsToSelector:@selector(buleToothTool:didReceiveStr:)]){
            [self.delegate buleToothTool:self didReceiveStr:value];
        }
        
    } else {
        DLog(@"未发现特征值.");
    }
}


#pragma mark -发送数据
- (BOOL)writeWithByte:(Byte *)sendData sendLength:(unsigned int)sendLength {

    NSData *data = [[NSData alloc] initWithBytes:sendData length:sendLength];
    if (_writeCharacteristic == nil) return NO;
    [self.peripheral writeValue:data forCharacteristic:_writeCharacteristic type:CBCharacteristicWriteWithResponse];
    return YES;
}

- (void)writeChar:(NSData *)data
{
    [self.peripheral writeValue:data forCharacteristic:_writeCharacteristic type:CBCharacteristicWriteWithResponse];
}


-(NSMutableArray *)peripherals{
    if(!_peripherals){
        _peripherals=[NSMutableArray array];
    }
    return _peripherals;
}


@end
